﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace First_Registry.Ioc
{
    public class ContainerExtension : IContainerProvider, IContainerRegistry, IContainerExtension
    {
        private readonly Dictionary<Type, Type> _transientRegistrations = new Dictionary<Type, Type>();
        private readonly Dictionary<Type, object> _singletonInstances = new Dictionary<Type, object>();
        private readonly Dictionary<Type, Type> _singletonRegistrations = new Dictionary<Type, Type>();

        private readonly object _lock = new object();

        public void RegisterTransient<TService, TImplementation>() where TImplementation : TService
        {
            _transientRegistrations[typeof(TService)] = typeof(TImplementation);
        }

        public void RegisterSingleton<TService, TImplementation>() where TImplementation : TService
        {
            _singletonRegistrations[typeof(TService)] = typeof(TImplementation);
        }

        public void RegisterInstance<TService>(TService instance)
        {
            _singletonInstances[typeof(TService)] = instance;
        }

        public T Resolve<T>()
        {
            return (T)Resolve(typeof(T));
        }

        public object Resolve(Type type)
        {
            // 优先从单例实例中查找
            if (_singletonInstances.ContainsKey(type))
            {
                return _singletonInstances[type];
            }

            // 查找瞬时注册
            if (_transientRegistrations.ContainsKey(type))
            {
                var implementationType = _transientRegistrations[type];
                return CreateInstance(implementationType);
            }

            // 查找单例注册
            if (_singletonRegistrations.ContainsKey(type))
            {
                var implementationType = _singletonRegistrations[type];
                lock (_lock)
                {
                    if (!_singletonInstances.ContainsKey(type))
                    {
                        var instance = CreateInstance(implementationType);
                        _singletonInstances[type] = instance;
                    }
                }
                return _singletonInstances[type];
            }

            throw new InvalidOperationException($"Type {type.Name} not registered.");
        }

        private object CreateInstance(Type type)
        {
            var constructor = type.GetConstructors().First();
            var parameters = constructor.GetParameters()
                                        .Select(param => Resolve(param.ParameterType))
                                        .ToArray();
            var instance = Activator.CreateInstance(type, parameters);

            foreach (var property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
            {
                if (property.IsDefined(typeof(InjectAttribute), true))
                {
                    var propertyInstance = Resolve(property.PropertyType);
                    property.SetValue(instance, propertyInstance);
                }
            }

            return instance;
        }

        public virtual void FinalizeExtension()
        {
            
        }
    }
}
